package com.esdk.utils;

/**
 * @author franky.fan
 */

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.esdk.esdk;
import com.esdk.interfaces.Adder;
import com.esdk.interfaces.Func;
import lombok.NonNull;

import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class EasyArray{
  public final static String[] EmptyStrArr=Constant.EmptyStrArr;
  public final static Long[] EmptyLongArr=Constant.EmptyLongArr;
  public final static Integer[] EmptyIntArr=Constant.EmptyIntArr;

	public static <T> T get(T[] array, int index){
		if(index < 0 || array == null || array.length <= index) return null;
		return array[index];
	}

	public static <T> T get(List<T> list, int index){
		if(index < 0 || list == null || list.size() <= index) return null;
		return list.get(index);
	}

	public static <T>T first(List<T> list){
		if(list==null||list.isEmpty())
			return null;
		return list.getFirst();
	}
	public static <T>T first(List<T> list,@NonNull T defVal){
		return esdk.obj.or(first(list),defVal);
	}
	public static <T>T first(T[] array){
		if(array==null||array.length==0)
			return null;
		return array[0];
	}
	public static <T>T first(T[] array,@NonNull T defVal){
		if(array==null||array.length==0)
			return defVal;
		return array[0];
	}
	public static boolean first(boolean[] array,boolean defVal){
		if(array==null||array.length==0)
			return defVal;
		return array[0];
	}
	public static <T>T last(T[] array){
		if(array==null||array.length==0)
			return null;
		return array[array.length-1];
	}
	public static <T>T last(T[] array,T defVal){
		if(array==null||array.length==0)
			return defVal;
		return array[array.length-1];
	}

	/**测试100万排序只需要2秒，没有性能问题*/
	public static <T extends Comparable>List<T> sort(@NonNull List<T> list){
		Collections.sort(list);
		return list;
	}

	/**测试100万排序只需要2秒，没有性能问题*/
	public static <T extends Comparable>List<T> sort(@NonNull List<T> list,boolean desc){
		Collections.sort(list,(o1,o2) ->desc?o2.compareTo(o1):o1.compareTo(o2));
		return list;
	}

	/**注意会有超过10万以上会有性能问题*/
	public static <T extends Comparable>T[] sort(@NonNull T[] obj){
		return sort(obj,false);
	}

	/**注意会有超过10万以上会有性能问题*/
	public static <T extends Comparable>T[] sort(@NonNull T[] obj,boolean desc){
		if(!desc){
			for(int i=obj.length-1;i>0;i--){
				for(int j=0;j<i;j++){
					if(obj[j].compareTo(obj[j+1])>0){ // >0
						T temp=obj[j+1];
						obj[j+1]=obj[j];
						obj[j]=temp;
					}
				}
			}
		}else{
			for(int i=obj.length-1;i>0;i--){
				for(int j=0;j<i;j++){
					if(obj[j].compareTo(obj[j+1])<0){ // <0
						T temp=obj[j+1];
						obj[j+1]=obj[j];
						obj[j]=temp;
					}
				}
			}
		}
		return obj;
	}
	
  public static <T> ArrayList<T> unique(@NonNull Collection<T> collection) {
  	ArrayList result=new ArrayList();
  	for(T item:collection) {
  		if(!result.contains(item))
  			result.add(item);
  	}
  	return result;
  }

	public static <T>T[] unique(T... array){
		return unique((Class<T>)getComponentType(array),array);
	}
	public static <T>T[] unique(T[]... array){
		T[] arr=concat(array);
		return unique((Class<T>)getComponentType(arr),arr);
	}
	public static <T>T[] unique(Class<T> cls,T[]... array){
		LinkedHashSet<T> result=new LinkedHashSet();
		for(T[] item:array){
			result.addAll(toList(item));
		}
		return (T[])result.toArray((T[])Array.newInstance(cls,result.size()));
	}

	public static <T>T[] unique(Class<T> cls,T... array){
		LinkedHashSet result=new LinkedHashSet(toList(array));
		return (T[])result.toArray((T[])Array.newInstance(cls,result.size()));
	}
  
  public static <T> ArrayList<T> distinct(@NonNull Collection<T> list) {
  	return unique(list);
  }

  public static <T>T[] distinct(T... array) {
  	return unique(array);
  }

	public static <T>T[] distinct(T[]... array) {
		return unique((T[][])array);
	}

	public static <T>T[] distinct(Class<T> cls,T... array) {
		return unique(cls,(T[])array);
	}
	public static <T>T[] distinct(Class<T> cls,T[]... array) {
		return unique(cls,(T[][])array);
	}

	public static String toStr(@NonNull Object[] array) {
  	return toStr(array,",");
  }
	public static String toStr(@NonNull Collection array) {
		return toStr(array.toArray(),",");
	}
	public static String toStr(@NonNull Collection array,String delimter) {
		return toStr(array.toArray(),delimter);
	}
  public static String toStr(@NonNull Object[] array,@NonNull String delimter) {
  	StringBuilder result=new StringBuilder();
  	for(Object obj:array) {
  		if(obj!=null) {
  			result.append(result.length()>0?delimter:"").append(obj);
  		}
  	}
  	return result.toString();
  }
	
	public static <T>T[] remove(T[] array,@NonNull T... removeItems){
		if(array==null||array.length==0)
			return array;
		List<T> result=toList(array);
		result.removeAll(toList(removeItems));
		return result.toArray((T[])Array.newInstance(getComponentType(array),result.size()));
	}

	/**
	 * 获取子数组
	 * */
	public static <T>T[] subArray(@NonNull T[] array,int begin,int end){
		T[] result=(T[])Array.newInstance(getComponentType(array),end-begin);
		System.arraycopy(array,begin,result,0,result.length);
		return result;
	}
	
	/**默认最大值为数组长度*/
	public static <T>T[] subArray(@NonNull T[] array,int begin){
		return subArray(array,begin,array.length);
	}
	
	/**取最多limit长度的子数组*/
	public static <T>T[] topArray(@NonNull T[] array,int limit){
		return subArray(array,0,limit);
	}
	
	public static <T> T[] filter(@NonNull T[] array,Predicate<T> fn) {
		return filter(array,0,fn);
	}
	
	public static <T> T filterFirst(T[] array,Predicate<T> fn) {
		T[] result=filter(array,1,fn);
		return result.length==0?null:result[0];
	}
	
	public static <T> @NonNull T[] filter(@NonNull T[] array,int top, Predicate<T> fn) {
		ArrayList<T> subList=new ArrayList<T>();
		if(top<=0)
			top=array.length;
		for(T item:array) {
			if(fn.test(item)) {
				if(top-->0)
					subList.add(item);
			}
		}
		T[] result=toArray(subList,(Class<T>)getComponentType(array,subList));
		return result;
	}
	
	public static <T> @NonNull T[] remove(@NonNull T[] array,T removeItems){
		if(array==null||array.length==0)
			return array;
		List<T> result=toList(array);
		result.remove(removeItems);
		return result.toArray((T[])Array.newInstance(getComponentType(array),result.size()));
	}
  
	private static <T> Class getComponentType(T[] array) {
		Class cls=array.getClass().getComponentType();
		while(cls.isArray()&&cls.getComponentType()!=null){
			cls=cls.getComponentType();
			if(cls!=null){
				if(cls.isArray())
					cls=getComponentType((T[])array[0]);
				if(cls!=null)
					break;
			}
		}
		return cls;
	}

	private static <T> Class getComponentType(List<T> list) {
		Class cls=list.isEmpty()?Object.class:list.get(0).getClass();
		return cls;
	}

	private static <T> Class getComponentType(T[] args,List<T> list) {
		Class cls=getComponentType(list);
		if(cls.equals(Object.class))
			cls=getComponentType(args);
		return cls;
	}
	
	/**Don't support int[],double[]...*/
	public static <T> @NonNull List<T> toList(@NonNull T...args){
		List<T> result=new ArrayList(args.length*4);
		for(int i=0;i<args.length;i++){
			if(args[i]==null)
				continue;
			if(args[i]!=null&&args[i].getClass().isArray())
				result.addAll(Arrays.asList((T[])args[i]));
			else if(args[i] instanceof Collection collection)
				result.addAll(collection);
			else 
				result.add((T)args[i]);
		}
		return result;
	}
	
	public static <T> @NonNull Set<T> toSet(T[] array){
		HashSet result=new HashSet(array.length);
		result.addAll(Arrays.asList(array));
		return result;
	}

	public static <T> @NonNull List<List<T>> partition(@NonNull T[] arr,int size){
		return ListUtil.partition(Arrays.asList(arr),size);
	}

	public static <T> @NonNull List<List<T>> partition(@NonNull List<T> list,int size){
		return ListUtil.partition(list,size);
	}
	
	/**把数组或对象合并成数组返回，如果全部参数都是数组，应使用concat()*/
	public static <T>@NonNull T[] concat(@NonNull T...args){
		List<T> result=toList(args);
		return result.toArray((T[])Array.newInstance(getComponentType(args,result),result.size()));
	}
	
	/**强制指定输出的数组类型，把数组或对象合并成数组返回，如果全部参数都是数组，应使用concat()*/
	public static <T>@NonNull T[] concat(Class<T> cls,@NonNull Object... args){
		List result=null;
		if(!esdk.array.isBlank(args)) { 
			result=toList(args);
			return (T[])result.toArray((T[])Array.newInstance(cls,result.size()));
		}else
			return (T[])Array.newInstance(cls,0);
	}
	
	/**拼接多个数组，返回合并后的数组，不作用重处理，在方法命名上把join区别*/
	public static <T>@NonNull T[] concat(@NonNull T[]... arrays){
		List<T> result=toList((T[])arrays);
		return result.toArray((T[])Array.newInstance(getComponentType((T[])arrays,result),result.size()));
	}
	
	/**拼接多个数组，返回合并后的数组*/
	public static <T>@NonNull T[] append(@NonNull T[] array, T...appends){
		List result=new ArrayList(array.length+appends.length);
		result.addAll(Arrays.asList(array));
		result.addAll(Arrays.asList(appends));
		return (T[])result.toArray((T[])Array.newInstance(getComponentType(array,result),result.size()));
	}

	/**拼接多个数组，返回合并后的数组
	 * @param distinct 记录去重
	 * */
	public static <T>@NonNull T[] append(@NonNull T[] array, T item,boolean distinct){
		List<T> list=new ArrayList(array.length+1);
		list.addAll(Arrays.asList(array));
		list.add(item);
		if(distinct)
			list=distinct(list);
		return toArray(list);
	}
	
	/**List不能为空，必须要拿到第一个元素的class*/
	public static <T>@NonNull T[] toArray(Collection<T> t){
		if(t==null)
			return null;
	  if(t.isEmpty())
			return (T[])new Object[0];//TODO应该会出异常，但目前没有找到更好的办法
		Class cls=t.iterator().next().getClass();
		return t.toArray((T[])Array.newInstance(cls,t.size()));
	}
	
	public static <T> @NonNull T[] sortByHash(@NonNull T[] array) {
		HashSet<T> set=new HashSet<T>(array.length);
		for(T col:array) {
			set.add(col);
		}
		return esdk.array.toArray(set);
	}

	public static <T>T[] toArray(Collection<T> t,Class<T> cls){
		if(t==null)
			return null; 
		return t.toArray((T[])Array.newInstance(cls,t.size()));
	}

	public static <T>@NonNull T[] toArray(T...array){
		return array;
	}

	public static <T>@NonNull T[] toArray(Class<T> cls,T...array){
		return ArrayUtil.toArray(Arrays.asList(array),cls);
	}

	public @NonNull Long[] toLongArray(String val) {
		return esdk.math.toLongArray(val);
	}
	
	public @NonNull Double[] toDoubleArray(String val) {
		return esdk.math.toDoubleArray(val);
	}
	
	public @NonNull Integer[] toIntArray(String val) {
		return esdk.math.toIntArray(val);
	}
	
	/**删除list实例的null元素*/
	public @NonNull List<?> removeNull(@NonNull AbstractList<?> list) {
		for(int i=list.size()-1;i>=0;i--){
			if(list.get(i)==null)
				list.remove(i);
		}
		return list;
	}
	
	public static boolean equals(@NonNull Object[] a,@NonNull Object[] b) {
		return Arrays.equals(a,b);
	}

	public static boolean contains(@NonNull Object[] array,@NonNull Object[] objs){
		for(int i=0;i<objs.length;i++){
			if(ArrayUtil.contains(array,objs[i]))
				return true;
		}
		return false;
	}

	
	/**得到两个集合的交集*/
	public static @NonNull String[] overlap(@NonNull String[] c1,@NonNull String[] c2){
		return (String[])overlap(Arrays.asList(c1),Arrays.asList(c2)).toArray(new String[0]);
	}
	
	/**得到两个集合的并集*/
	public static <C extends Collection> @NonNull Set merge(@NonNull C c1,@NonNull C c2){
		LinkedHashSet result=new LinkedHashSet(c1);
		result.addAll(c2);
		return result;
	}
	
	/**得到两个集合的并集*/
	public static  <C> @NonNull C[] merge(@NonNull C[] c1,@NonNull C[] c2){
		return (C[])toArray(merge(Arrays.asList(c1),Arrays.asList(c2)));
	}

	public static  @NonNull Integer[] distinct(@NonNull Integer[] array){
		LinkedHashSet result=new LinkedHashSet();
		for(int i=0;i<array.length;i++){
			result.add(array[i]);
		}
		return (Integer[])result.toArray(new Integer[0]);
	}

	public static @NonNull Long[] distinct(@NonNull Long[] array){
		LinkedHashSet result=new LinkedHashSet();
		for(int i=0;i<array.length;i++){
			result.add(array[i]);
		}
		return (Long[])result.toArray(new Long[0]);
	}

  /**array1包含array2任意一个数，返回true*/
	public static <C> boolean existOr(@NonNull C[] arrayAll,@NonNull C[] arraySub){
		if(ArrayUtil.isEmpty(arraySub)||ArrayUtil.isEmpty(arrayAll))
			return false;
		for(int i=0;i<arrayAll.length;i++){
			for(int j=0;j<arraySub.length;j++){
				if(arrayAll[i]==arraySub[j])
					return true;
			}
		}
		return false;
	}
  
	 /**array1包含array2所有数，返回true*/
	public static <C> boolean existAnd(@NonNull C[] arrayAll,@NonNull C[] arraySub){
		if(ArrayUtil.isEmpty(arraySub)||ArrayUtil.isEmpty(arrayAll))
			return false;
		else
			return overlap(arrayAll,arraySub).length==arraySub.length;
	}
	
	/**得到两个集合的交集*/
	public static <T> @NonNull Collection<T> overlap(Collection<T> c1,Collection<T> c2){
		LinkedHashSet result=new LinkedHashSet();
		if(c1==c2)
			return c1;
		else if(c1==null||c1.size()==0||c2==null||c2.size()==0)
			return result;
		for(Iterator iter=c1.iterator();iter.hasNext();){
			Object o1=iter.next();
			for(Iterator iterator=c2.iterator();iterator.hasNext();){
				Object o2=iterator.next();
				if(ObjectUtil.equal(o1,o2)){
					result.add(o2);
				}
			}
		}
		return result;
	}
	/**
	 * @param sortedSrc 源列表，必须已排序
	 * @param sortedDist 目标列表，必须已排序
	 * @return 在目标列表中能找到的源列表记录的数据集
	 * */
	public static <C extends Comparable> @NonNull List<C> in(@NonNull List<C> sortedSrc,@NonNull List<C> sortedDist){
		ArrayList result=new ArrayList();
		int i=0,n=sortedSrc.size(),j=0, m=sortedDist.size();
		for(;i<n;i++){
			Comparable itemSrc=sortedSrc.get(i);
			if(i<=j || j<m){
				for(;j<m;j++){
					Comparable itemDist=sortedDist.get(j);
					int flag=itemSrc.compareTo(itemDist);
					if(flag<0){
						break;
					}else if(flag==0){
						result.add(itemSrc);
						j++;
						break;
					}
				}
			}else{
				result.add(itemSrc);
			}
		}
		return result;
	}

	/**
	 * @param sortedSrc 源列表，必须已排序
	 * @param sortedDist 目标列表，必须已排序
	 * @return 未能在目标列表中找到的源列表的数据集
	 * */
	public static <C extends Comparable> @NonNull List<C> notIn(@NonNull List<C> sortedSrc,@NonNull List<C> sortedDist){
		ArrayList result=new ArrayList();
		int srcIndex=0,srcSize=sortedSrc.size(),distIndex=0, distSize=sortedDist.size();
		for(;srcIndex<srcSize;srcIndex++){
			Comparable itemSrc=sortedSrc.get(srcIndex);
			if(distIndex<distSize){
				for(;distIndex<distSize;distIndex++){
					Comparable itemDist=sortedDist.get(distIndex);
					int flag=itemSrc.compareTo(itemDist);
					if(flag==0){
						distIndex++;
						break;
					}
					else if(flag<0){
						result.add(itemSrc);
						break;
					}
					else if(flag>0 && distIndex==distSize-1){
						result.add(itemSrc);
					}
				}
			}
			else{
				result.add(itemSrc);
			}
		}
		return result;
	}

	/**
	 * @param sortedSrc 源列表，必须已排序
	 * @param sortedDist 目标列表，必须已排序
	 * @return 未能在目标列表中找到的源列表的数据项的索引值列表
	 * */
	public static @NonNull List<Integer> notIndex(@NonNull List<Comparable> sortedSrc,@NonNull List<Comparable> sortedDist){
		ArrayList<Integer> result=new ArrayList();
		int i=0,n=sortedSrc.size(),j=0, m=sortedDist.size();
		for(;i<n;i++){
			Comparable itemSrc=sortedSrc.get(i);
			if(i<=j || j<m){
				for(;j<m;j++){
					Comparable itemDist=sortedDist.get(j);
					int flag=itemSrc.compareTo(itemDist);
					if(flag<0){
						result.add(i);
						break;
					}else if(flag==0){
						j++;
						break;
					}
				}
			}else{
				result.add(i);
			}
		}
		return result;
	}

	public static <Comparable> @NonNull List<Comparable> getListByIndex(@NonNull List<Comparable> list,@NonNull List<Integer> indexList){
		List<Comparable> result=new ArrayList<>();
		for(int i=0;i<indexList.size();i++){
			result.add(list.get(i));
		}
		return result;
	}

	/**得到两个集合的交集*/
	public static <C> @NonNull C[] overlap(@NonNull C[] c1,@NonNull C[] c2){
		Collection c3=overlap(Arrays.asList(c1),Arrays.asList(c2));
		Class cls=null;
		if(c1!=null&&c1.length>0)
			cls=c1[0].getClass();
		else if(c2!=null&&c2.length>0)
			cls=c2[0].getClass();
		if(cls==null)
			return null;
		else
			return (C[])esdk.array.toArray(c3,cls);
	}

	public static <T> int indexOf(@NonNull T[] array,@NonNull T obj){
		return ArrayUtil.indexOf(array,obj);
	}

	public static <T> int indexOf(byte[] array, byte[] subArray) {
		int result=-1;
		if (null != array && subArray!=null) {
			for (int i = 0; i < array.length; i++) {
				boolean pass=true;
				for(int j=0,k=i;pass && j<subArray.length;j++,k++) {
					if(array[k]!=subArray[j])
						pass=false;
				}
				if(pass) {
					result=i;
					break;
				}
			}
		}
		return result;
	}

	
	public static boolean contains(@NonNull Object[] array,Object obj){
		return ArrayUtil.contains(array,obj);
	}

	public static int indexOf(@NonNull int[] array,int obj){
		return ArrayUtil.indexOf(array,obj);
	}

	public static boolean contains(@NonNull int[] array,int obj){
		return ArrayUtil.indexOf(array,obj)>0;
	}

	public static boolean contains(@NonNull String[] array,@NonNull String[] objs){
		for(int i=0;i<objs.length;i++){
			if(indexOf(array,objs[i])<0)
				return false;
		}
		return true;
	}
	
	public static <T> String toString(T[] array) {
		return EasyStr.valueOf(array);
	}
	
	public static boolean isEmpty(Object[] arr) {
		return ArrayUtil.isEmpty(arr);
	}

	public static boolean isValid( Object[] arr) {
		return !ArrayUtil.isEmpty(arr);
	}

	public static boolean isBlank(Object[] arr){
		return arr==null || arr.length==0;
	}

	public static Comparable getComparableArray(Object[] arr){
		return new ComparableArray(arr);
	}

	/**弹出所有栈记录，解决List删除记录的并发问题*/
	public static <T> @NonNull List<T> pollAll(@NonNull ConcurrentLinkedQueue<T> rowList){
		ArrayList<T> result=new ArrayList();
		T item;
		while((item=rowList.poll())!=null){
			result.add(item);
		}
		if(result.size()>=10000){
			esdk.warn(result.get(0).getClass().getName()+" count is "+result.size());
		}
		return result;
	}

	/**弹出多个栈记录，解决List删除记录的并发问题*/
	public static <T> @NonNull List<T> poll(@NonNull ConcurrentLinkedQueue<T> rowList,int limit){
		ArrayList<T> result=new ArrayList();
		T item;
		while((item=rowList.poll())!=null&&result.size()<limit){
			result.add(item);
		}
		if(result.size()>=10000){
			esdk.warn(result.get(0).getClass().getName()+" count is "+result.size());
		}
		return result;
	}

	public static <E> Adder reduce(Collection<E> list,Function<E,?> fn){
		Adder result=new CharAppender(',',true);
		for(E item:list){
			result.add(fn.apply(item));
		}
		return result;
	}

	/**
	 * @param nullable 为false则忽略null值
	 * */
	public static <E> Adder reduce(@NonNull Collection<E> list,boolean nullable,Function<E,?> fn){
		Adder result=new CharAppender(',',true);
		for(E item:list){
			Object v=fn.apply(item);
			if(nullable||v!=null)
				result.add(v);
		}
		return result;
	}

	public static <Rtn extends Adder,Item> Rtn reduce(@NonNull Collection<Item> list,Rtn result,Function<Item,?> fn){
		for(Item item:list){
			result.add(fn.apply(item));
		}
		return result;
	}

	@SafeVarargs
  public static <T, R> R[] getValues(@NonNull Func<T, R> func,@NonNull T ...objs){
		return (R[])Stream.of(objs).map(esdk.func.asFunction(func)).toArray();
	}

	public static <T,R> R[] map(@NonNull T[] arr,@NonNull Func<T,R> func){
		ArrayList result=new ArrayList(arr.length);
		for(T item:arr){
			try{
				result.add(func.invoke(item));
			}catch(Exception e){
				throw esdk.tool.wrapThrowble(e);
			}
		}
		return (R[])result.toArray();
	}

	public static <T,R> List<R> map(@NonNull List<T> list,@NonNull Func<T,R> func){
		ArrayList<R> result=new ArrayList();
		for(T item:list){
      try{
        result.add(func.invoke(item));
      }catch(Exception e){
        throw esdk.tool.wrapThrowble(e);
      }
    }
		return result;
	}

	public static <T,R> List<R> toList(@NonNull List<T> list,@NonNull Func<T,R> func){
		return map(list,func);
	}

	public static void main(String[] args){
		esdk.tool.assertEquals(esdk.str.arrToStr(concat(new String[] {})),"");
		Integer[] n1=new Integer[] {1,2,3};
		esdk.tool.assertEquals(esdk.str.valueOf(concat(n1,4,5)),"1,2,3,4,5");
		String[] s1=new String[] {"a","b"};
//		Integer[] b=new Integer[] {1,2};
		String[] s2=new String[] {"c","d"};
//		Tools.assertEquals(concat(a,b).length,4);	
		esdk.tool.assertEquals(esdk.str.valueOf(concat(s1,s2,"e","f","g")),esdk.str.valueOf(distinct("a,a,b,c,d,e,f,g".split(","))));
		esdk.tool.assertEquals(esdk.str.valueOf(remove(s1,"a","b".split(","))),"");
		esdk.tool.assertEquals(esdk.str.valueOf(unique(s1,s2,"a","e","f,g".split(","))),"a,b,c,d,e,f,g");
		Object[] ns=concat(Object.class,n1,s1);
		esdk.tool.assertEquals(esdk.json.toJSON(ns).toString(),"[1,2,3,\"a\",\"b\"]");
		esdk.tool.assertEquals(EasyStr.valueOf(merge(new String[] {"a","c","b"},new String[] {"c","d","a"})),"a,c,b,d");
		String[] arr={"a","b","c","d"};
		esdk.tool.assertEquals(EasyStr.valueOf(subArray(arr,1,4)),"b,c,d");
		String[] s3= {"valid","createTime","createUserId","createUserName"};
		esdk.tool.assertEquals(esdk.str.valueOf(filter(s3,2,e->!e.endsWith("Id"))),"valid,createTime");
		byte[] aa={0x37,0x66,0x07,0x1a,0x12,0x3a,0x4c,(byte)0x9f,(byte)0xa9,0x5d,0x21,(byte)0xd2,(byte)0xda,0x7d,0x26,(byte)0xbc};
		byte[] a= {(byte)0x9f,(byte)0xa9,(byte)0x5d};
		esdk.tool.assertEquals(indexOf(aa,a),7);
		esdk.tool.assertEquals(esdk.array.notIn(esdk.array.toList(1,2,4),esdk.array.toList(1,2,3)),esdk.array.toList(4));
		esdk.tool.assertEquals(esdk.array.notIn(esdk.array.toList(1,2,4,6,7,8,9),esdk.array.toList(1,3,4,5,6,7,8,10)),esdk.array.toList(2,9));
		esdk.tool.assertEquals(esdk.array.notIn(esdk.array.toList(1,2,4,6,7,8,9),esdk.array.toList(1,3,4,5,6,7,8,10)),esdk.array.toList(2,9));
		esdk.tool.assertEquals(esdk.array.notIn(esdk.array.toList(1,2,4,6,7,8,9),esdk.array.toList(3,4,5,6,7,8,9)),esdk.array.toList(1,2));
		esdk.tool.printAssertInfo();
	}

}
